home *** CD-ROM | disk | FTP | other *** search
- /* -- exec.h --
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <setjmp.h>
-
- #ifndef STRATOM_H
- #include "stratom.h"
- #endif
-
- #ifndef YES
- #define YES 1
- #define NO 0
- typedef int BOOL;
- #endif
-
- #ifndef BIT
- #define BIT(i) (1 << (i))
- #endif
-
- /* different perfixes for EXEC_ID
- */
- #define PORT_PREFIX BIT(15)
- #define SEMAPHORE_PREFIX BIT(14)
- #define TIMER_PREFIX BIT(13)
- #define MONOSTABLE_PREFIX BIT(12)
- #define TRIGGER_PREFIX BIT(11)
-
- #define BAD_EXEC_ID 0
-
- typedef int EXEC_ID;
- typedef unsigned char THREAD_ID;
-
- typedef unsigned int PORT;
- typedef unsigned int SEMAPHORE;
-
- /* process type. Not used yet
- */
- typedef enum
- { NORMAL_PROC = 10, HALTABLE_PROC, INHIBITABLE_PROC }
- PROCESS_TYPE;
-
- void *ExecAlloc(unsigned int size);
- THREAD_ID ExecCreateThread(PROCESS_TYPE procType,
- void (*pFunction)(void), unsigned int stackSize,
- unsigned long arg0, unsigned long arg1);
- THREAD_ID ExecGetThreadID(void);
- void ExecInit(void);
- void ExecStart(void);
-
- void MsgClearSemaphore(STRING_ATOM semaphoreAtom);
- BOOL MsgConnectPorts(STRING_ATOM sourceAtom,
- STRING_ATOM destinationAtom);
- void MsgDeleteTimer(EXEC_ID watchID);
- EXEC_ID MsgGetMsg(void);
- BOOL MsgInhibitPorts(STRING_ATOM sourceAtom,
- STRING_ATOM destinationAtom);
- void *MsgOpenPort(STRING_ATOM nameAtom, PORT *pPortValue);
- PORT MsgPeekPort(STRING_ATOM, PORT *);
- void MsgSetSemaphore(STRING_ATOM semaphoreAtom);
- BOOL MsgSuppressPorts(STRING_ATOM sourceAtom,
- STRING_ATOM destinationAtom);
- EXEC_ID MsgWatchPort(STRING_ATOM portAtom, PORT *pPortValue);
- EXEC_ID MsgWatchSemaphore(STRING_ATOM semaphoreAtom, BOOL detectOn);
- EXEC_ID MsgWatchTimer(unsigned int interval);
- void MsgWriteToPort(STRING_ATOM portAtom, PORT portValue);
-
- #define MsgWatchTrigger(portAtom) MsgWatchPort(portAtom, NULL)
-
- void SysLEDs(int i);
-
- typedef unsigned
- #ifdef HC11
- int
- #else
- long
- #endif
- EXEC_ARG;
-
- extern EXEC_ARG ExecArg0, ExecArg1;
-
- /* -- exec.c --
- */
- #include <stdlib.h>
- #include <string.h>
- #include "exec.h"
- #include "execpriv.h"
-
- /* arguments to threads
- */
- EXEC_ARG ExecArg0;
- EXEC_ARG ExecArg1;
-
- /* number of possible threads
- */
- #ifndef NUMBER_OF_THREADS
- #define NUMBER_OF_THREADS 34
- #endif
-
- /* process state
- */
- typedef enum
- { INIT_STATE = 20, RUNNING_STATE, WAIT_STATE }
- PROCESS_STATE;
-
- /* context for thread
- */
- typedef struct
- {
- THREAD_ID threadID;
- void (*pFunction)(void);
- PROCESS_TYPE procType;
- PROCESS_STATE procState;
- jmp_buf exitContext;
- jmp_buf switchContext;
- char *stackTop;
- char *stackBottom;
- EXEC_ARG arg0;
- EXEC_ARG arg1;
- } THREAD_CONTEXT;
-
- /* file static variables
- */
- static BOOL hasCreatedThreads;
- static THREAD_CONTEXT threadTable[NUMBER_OF_THREADS];
- static THREAD_ID execCurrentThreadID;
-
- static void execRunNewThread(void);
-
- /* allocate a block of memory, zeroed out
- */
- void *ExecAlloc(unsigned int size)
- {
- void *p;
-
- p = calloc(1, size);
- if (!p)
- {
- #ifndef HC11
- printf("no memory\n");
- #endif
- exit(1);
- }
- return (p);
- }
-
- /* thread function returns here, jump to exit context
- */
- void ExecCallReturn(void)
- {
-
- longjmp(threadTable[execCurrentThreadID].exitContext,
- execCurrentThreadID);
- }
-
- /* create a thread context
- */
- THREAD_ID ExecCreateThread(PROCESS_TYPE procType, void (*pFunction)(void),
- unsigned int stackSize, unsigned long arg0, unsigned long arg1)
- {
- char *stack;
- THREAD_ID i;
-
- /* find the next free entry in table
- */
- for (i = 0; i < NUMBER_OF_THREADS && threadTable[i].procState; ++i)
- ;
- if (i == NUMBER_OF_THREADS)
- return (BAD_EXEC_ID);
- hasCreatedThreads = YES;
- /* clear entry and allocate stack
- */
- memset(&threadTable[i], '\0', sizeof (THREAD_CONTEXT));
- /* stack space used by the executive, i.e. by the functions MsgGetMsg()
- * and ExecSwitch()
- */
- stackSize &= ~0x3; /* quad byte aligned */
- #define EXEC_STACK_SIZE 40
- stackSize += EXEC_STACK_SIZE;
- stack = SysGetStack(stackSize);
- threadTable[i].procType = procType;
- threadTable[i].pFunction = pFunction;
- threadTable[i].stackBottom = stack;
- threadTable[i].stackTop = stack + stackSize;
- threadTable[i].procState = INIT_STATE;
- /* memorize the initail arguments to function
- */
- threadTable[i].arg0 = arg0;
- threadTable[i].arg1 = arg1;
- /* put this on the runnable queue
- */
- MsgEnQueue(i, i);
- return (i);
- }
-
- /* return a new id
- */
- EXEC_ID execExecID(unsigned int prefix)
- {
- static unsigned int i;
-
- return (prefix | (++i));
- }
-
- /* return the current thread id
- */
- THREAD_ID ExecGetThreadID(void)
- {
-
- return (execCurrentThreadID);
- }
-
- /* initialize the system
- */
- void ExecInit(void)
- {
- SysInit();
- }
-
- /* take the first thread off the runnable queue and give execution to it
- */
- static
- void execRunNewThread(void)
- {
- EXEC_ID returnID;
- PROCESS_STATE procState;
-
- /* take the first thread off the queue
- */
- execCurrentThreadID = MsgDeQueue(&returnID);
- SysLEDs(execCurrentThreadID);
- /* set process state
- */
- procState = threadTable[execCurrentThreadID].procState;
- threadTable[execCurrentThreadID].procState = RUNNING_STATE;
- /* procState == WAIT_STAT - use longjmp() to switch back to the old
- * execution context
- */
- if (procState != INIT_STATE)
- longjmp(threadTable[execCurrentThreadID].switchContext, returnID);
- else
- {
- /* initial call to a thread. Put thread arguments
- in the external
- * variables and call an assembly routine to call the thread
- */
- if (setjmp(threadTable[execCurrentThreadID].exitContext) == 0)
- {
- ExecArg0 = threadTable[execCurrentThreadID].arg0;
- ExecArg1 = threadTable[execCurrentThreadID].arg1;
- ExecCall(threadTable[execCurrentThreadID].pFunction,
- threadTable[execCurrentThreadID].stackTop);
- }
- /* thread dies, reclaim thread table entry (but
- not stack space)
- * and run the next available thread
- */
- threadTable[execCurrentThreadID].procState = 0;
- /* need to delete from all queues and ports
- */
- execRunNewThread();
- }
- }
-
- /* start the system.
- */
- void ExecStart(void)
- {
-
- if (hasCreatedThreads)
- execRunNewThread();
- }
-
- /* switch to a new thread
- */
- EXEC_ID ExecSwitch(void)
- {
- EXEC_ID watchID;
-
- /* check for stack overflow
- */
- if ((char *)&watchID < threadTable[execCurrentThreadID].stackBottom)
- {
- #ifndef HC11
- printf("stack overflow\n");
- #endif
- exit(1);
- }
- /* set up our return context and switch
- */
- if ((watchID = setjmp(threadTable[execCurrentThreadID].switchContext)) == 0)
- {
- threadTable[execCurrentThreadID].procState = WAIT_STATE;
- execRunNewThread();
- }
- return (watchID);
- }
-
-